<?php
/** 
 * @author 陈铭
 * @desc 上传文件类
 */
class Uploader {
	// TODO - Insert your code here
	public $extension;
	public $md5;
	
	private $filename;
	private $path;
	private $block;
	private $message;
	private $max_size;
	private $allow_type;
	private $allow_extension;
	
	/**
	 */
	function __construct($block) {
		$this->block = $block;
		$this->max_size = $this->return_bytes ( ini_get ( 'upload_max_filesize' ) );
		$this->allow_type = array ();
		$this->allow_extension = array ();
	}
	
	/**
	 */
	function __destruct() {
	}
	
	/**
	 * 设置目标目录
	 *
	 * @param string $path        	
	 */
	function setDestination($path) {
		$this->path = $path;
	}
	
	/**
	 * 设置目标文件名
	 * 
	 * @param string $filename        	
	 */
	function setFilename($filename) {
		$this->filename = $filename;
	}
	
	/**
	 * 设置有效的MIME
	 * 
	 * @param mixed $mimes        	
	 */
	function setMimes($mimes) {
		$this->allow_type = $mimes;
	}
	
	/**
	 * 设置有效的后缀名
	 * 
	 * @param mixed $extension        	
	 */
	function setExtensions($extensions) {
		$this->allow_extension = $extensions;
	}
	
	/**
	 * 检查上传有效性
	 * 
	 * @param unknown $extensions        	
	 */
	function vaild() {
		if (empty ( $_FILES )) {
			$this->message = '无效的上传。';
			return false;
		}
		
		$field = $_FILES [$this->block];
		
		if (! isset ( $field )) {
			$this->message = '指定的区块无效';
			return false;
		}
		
		// 处理文件错误信息
		switch ($field ['error']) {
			case 1 : // UPLOAD_ERR_INI_SIZE
				$this->message = '上传的文件大小超过了系统配置的限制。';
				return false;
			case 2 : // UPLOAD_ERR_FORM_SIZE
				$this->message = '上传文件的大小超过了表单规定的最大值。';
				return false;
			case 3 : // UPLOAD_ERR_PARTIAL
				$this->message = '文件只有部分被上传。';
				return false;
			case 6 :
				$this->message = '找不到临时文件夹。';
				return false;
			case 7 :
				$this->message = '文件写入失败。';
				return false;
		}
		
		// 检查文件大小
		if ($field ['size'] > $this->max_size) {
			$this->message = '上传文件超过了限制(' . $this->max_size . ')。';
			return false;
		}
		
		// 检查文件Mime类型
		if (! empty ( $this->allow_type ) && ! in_array ( strtolower ( $field ['type'] ), $this->allow_type )) {
			$this->message = '上传文件MIME类型不允许(' . $field ['type'] . ')。';
			return false;
		}
		
		// 检查文件后缀类型
		$pathinfo = pathinfo ( $field ['name'] );
		$this->extension = isset ( $pathinfo ['extension'] ) ? strtolower ( $pathinfo ['extension'] ) : '';
		if (! empty ( $this->allow_extension ) && ! in_array ( $this->extension, $this->allow_extension, TRUE )) {
			$this->message = '上传的文件后缀类型不允许。';
			return false;
		}
		
		// 检查是否合法上传
		if (! is_uploaded_file ( $field ['tmp_name'] )) {
			$this->message = '非法上传文件。';
			return false;
		}
		
		// 如果是图像文件 检测文件格式
		if (! in_array ( $this->extension, array (
				'gif',
				'jpg',
				'jpeg',
				'bmp',
				'png',
				'swf' 
		) ) && FALSE === getimagesize ( $field ['tmp_name'] )) {
			$this->message = '非法图像文件。';
			return false;
		}
		
		//取得文件MD5
		$this->md5 = md5_file($field['tmp_name']);
		
		return true;
	}
	
	/**
	 * 接收文件
	 *
	 * @return boolean
	 */
	function receive() {
		if (sizeof ( $_FILES ) == 0) {
			$this->message = '无效的文件上传请求。';
			return false;
		}
		
		$source = $_FILES [$this->block]['tmp_name'];
		$target = rtrim($this->path, '/') . '/' . $this->filename;
		
		return move_uploaded_file($source, $target);
	}
	
	/**
	 * 取得返回信息
	 */
	function getMessage() {
		return $this->message;
	}
	
	/**
	 * 递归创建新文件夹
	 *
	 * @param string $dir        	
	 * @return boolean
	 */
	function mkdirs($dir) {
		if (! is_dir ( $dir )) {
			if (! $this->mkdirs ( dirname ( $dir ) )) {
				return false;
			}
			if (! mkdir ( $dir, 0777 )) {
				return false;
			}
		}
		return true;
	}
	
	/**
	 * 取得转换的字节数
	 *
	 * @param string $val        	
	 * @return Ambigous <number, string>
	 */
	private function return_bytes($val) {
		$val = trim ( $val );
		$last = strtolower ( $val {strlen ( $val ) - 1} );
		switch ($last) {
			// The 'G' modifier is available since PHP 5.1.0
			case 'g' :
				$val *= 1024;
			case 'm' :
				$val *= 1024;
			case 'k' :
				$val *= 1024;
		}
		
		return $val;
	}
}

?>